//! # 企业级安全框架集成测试
//!
//! 全面测试 rustcloud-auth 企业级安全框架的各项功能

use std::sync::Arc;
use std::collections::HashMap;
use tokio;
use rustcloud_auth::prelude::*;
use rustcloud_auth::config::RustCloudAuthConfig;
use rustcloud_auth::service::{AuthServiceBuilder, AuthServiceConfig};

/// 测试用的模拟认证提供者
struct MockAuthProvider {
    name: String,
    should_succeed: bool,
}

impl MockAuthProvider {
    fn new(name: &str, should_succeed: bool) -> Self {
        Self {
            name: name.to_string(),
            should_succeed,
        }
    }
}

#[async_trait::async_trait]
impl rustcloud_security::auth::AuthProvider for MockAuthProvider {
    async fn authenticate(&self, context: &AuthContext) -> SecurityResult<Principal> {
        if self.should_succeed {
            let mut principal = Principal::new(
                "test_user".to_string(),
                "Test User".to_string(),
                PrincipalType::User,
            );
            
            // 添加一些测试权限
            principal = principal
                .add_role("user".to_string())
                .add_permission("read:posts".to_string())
                .add_permission("write:comments".to_string());
                
            Ok(principal)
        } else {
            Err(SecurityError::AuthenticationFailed {
                reason: "Mock authentication failure".to_string(),
            })
        }
    }

    async fn validate_token(&self, _token: &str) -> SecurityResult<bool> {
        Ok(self.should_succeed)
    }

    fn provider_type(&self) -> AuthProviderType {
        AuthProviderType::Custom(self.name.clone())
    }

    fn provider_name(&self) -> &str {
        &self.name
    }

    async fn refresh_token(&self, _refresh_token: &str) -> SecurityResult<String> {
        if self.should_succeed {
            Ok("new_token".to_string())
        } else {
            Err(SecurityError::AuthenticationFailed {
                reason: "Token refresh failed".to_string(),
            })
        }
    }

    async fn logout(&self, _principal: &Principal) -> SecurityResult<()> {
        Ok(())
    }

    async fn get_user_info(&self, principal: &Principal) -> SecurityResult<serde_json::Value> {
        Ok(serde_json::json!({
            "id": principal.id,
            "name": principal.name,
            "email": format!("{}@example.com", principal.id)
        }))
    }

    fn supports_token_refresh(&self) -> bool {
        true
    }
}

/// 测试基础认证功能
#[tokio::test]
async fn test_basic_authentication() {
    let config = AuthServiceConfig::default();
    let mock_provider = Arc::new(MockAuthProvider::new("mock", true));
    
    let auth_service = AuthServiceBuilder::new()
        .add_provider("mock".to_string(), mock_provider)
        .with_default_provider("mock".to_string())
        .build()
        .await
        .expect("Failed to build auth service");

    let context = AuthContext::new(
        HashMap::new(),
        "GET".to_string(),
        "/api/test".to_string(),
        Some("127.0.0.1".to_string()),
    );

    let result = auth_service.authenticate(&context).await;
    assert!(result.is_ok());
    
    let principal = result.unwrap();
    assert_eq!(principal.id, "test_user");
    assert_eq!(principal.name, "Test User");
    assert!(principal.has_role("user"));
    assert!(principal.has_permission("read:posts"));
}

/// 测试认证失败场景
#[tokio::test]
async fn test_authentication_failure() {
    let config = AuthServiceConfig::default();
    let mock_provider = Arc::new(MockAuthProvider::new("mock", false));
    
    let auth_service = AuthServiceBuilder::new()
        .add_provider("mock".to_string(), mock_provider)
        .with_default_provider("mock".to_string())
        .build()
        .await
        .expect("Failed to build auth service");

    let context = AuthContext::new(
        HashMap::new(),
        "GET".to_string(),
        "/api/test".to_string(),
        Some("127.0.0.1".to_string()),
    );

    let result = auth_service.authenticate(&context).await;
    assert!(result.is_err());
}

/// 测试权限检查
#[tokio::test]
async fn test_authorization() {
    let config = AuthServiceConfig::default();
    let mock_provider = Arc::new(MockAuthProvider::new("mock", true));
    
    let auth_service = AuthServiceBuilder::new()
        .add_provider("mock".to_string(), mock_provider)
        .with_default_provider("mock".to_string())
        .with_permission_enabled(true)
        .build()
        .await
        .expect("Failed to build auth service");

    let context = AuthContext::new(
        HashMap::new(),
        "GET".to_string(),
        "/api/test".to_string(),
        Some("127.0.0.1".to_string()),
    );

    let principal = auth_service.authenticate(&context).await.unwrap();
    
    let resource = Resource::new(
        "test-service".to_string(),
        "/api/posts".to_string(),
        "GET".to_string(),
    );

    let result = auth_service.authorize(&principal, &resource).await;
    assert!(result.is_ok());
    assert!(result.unwrap());
}

/// 测试令牌刷新
#[tokio::test]
async fn test_token_refresh() {
    let config = AuthServiceConfig::default();
    let mock_provider = Arc::new(MockAuthProvider::new("mock", true));
    
    let auth_service = AuthServiceBuilder::new()
        .add_provider("mock".to_string(), mock_provider)
        .with_default_provider("mock".to_string())
        .build()
        .await
        .expect("Failed to build auth service");

    let result = auth_service.refresh_token("old_refresh_token").await;
    assert!(result.is_ok());
    assert_eq!(result.unwrap(), "new_token");
}

/// 测试会话管理
#[tokio::test]
async fn test_session_management() {
    let config = AuthServiceConfig::default();
    let mock_provider = Arc::new(MockAuthProvider::new("mock", true));
    
    let auth_service = AuthServiceBuilder::new()
        .add_provider("mock".to_string(), mock_provider)
        .with_default_provider("mock".to_string())
        .with_memory_session_manager()
        .build()
        .await
        .expect("Failed to build auth service");

    let principal = Principal::new(
        "test_user".to_string(),
        "Test User".to_string(),
        PrincipalType::User,
    );

    // 创建会话（注意：这里需要通过会话管理器创建）
    // 由于 AuthService 没有直接暴露会话创建接口，这个测试可能需要调整
    // 或者我们需要在 AuthService 中添加会话管理的公共接口
}

/// 测试多提供者认证
#[tokio::test]
async fn test_multiple_providers() {
    let config = AuthServiceConfig::default();
    let jwt_provider = Arc::new(MockAuthProvider::new("jwt", true));
    let api_key_provider = Arc::new(MockAuthProvider::new("api_key", false));
    
    let auth_service = AuthServiceBuilder::new()
        .add_provider("jwt".to_string(), jwt_provider)
        .add_provider("api_key".to_string(), api_key_provider)
        .with_default_provider("jwt".to_string())
        .build()
        .await
        .expect("Failed to build auth service");

    // 测试提供者列表
    let providers = auth_service.list_providers();
    assert!(providers.contains(&"jwt".to_string()));
    assert!(providers.contains(&"api_key".to_string()));

    // 测试默认提供者认证
    let context = AuthContext::new(
        HashMap::new(),
        "GET".to_string(),
        "/api/test".to_string(),
        Some("127.0.0.1".to_string()),
    );

    let result = auth_service.authenticate(&context).await;
    assert!(result.is_ok());
}

/// 测试用户信息获取
#[tokio::test]
async fn test_get_user_info() {
    let config = AuthServiceConfig::default();
    let mock_provider = Arc::new(MockAuthProvider::new("mock", true));
    
    let auth_service = AuthServiceBuilder::new()
        .add_provider("mock".to_string(), mock_provider)
        .with_default_provider("mock".to_string())
        .build()
        .await
        .expect("Failed to build auth service");

    let principal = Principal::new(
        "test_user".to_string(),
        "Test User".to_string(),
        PrincipalType::User,
    );

    let user_info = auth_service.get_user_info(&principal).await;
    assert!(user_info.is_ok());
    
    let info = user_info.unwrap();
    assert_eq!(info["id"], "test_user");
    assert_eq!(info["name"], "Test User");
}

/// 测试权限检查
#[tokio::test]
async fn test_permission_check() {
    let config = AuthServiceConfig::default();
    let mock_provider = Arc::new(MockAuthProvider::new("mock", true));
    
    let auth_service = AuthServiceBuilder::new()
        .add_provider("mock".to_string(), mock_provider)
        .with_default_provider("mock".to_string())
        .build()
        .await
        .expect("Failed to build auth service");

    let context = AuthContext::new(
        HashMap::new(),
        "GET".to_string(),
        "/api/test".to_string(),
        Some("127.0.0.1".to_string()),
    );

    let principal = auth_service.authenticate(&context).await.unwrap();
    
    // 测试具有的权限
    let has_permission = auth_service.check_permission(&principal, "read:posts").await;
    assert!(has_permission.is_ok());
    assert!(has_permission.unwrap());
    
    // 测试没有的权限
    let no_permission = auth_service.check_permission(&principal, "delete:users").await;
    assert!(no_permission.is_ok());
    assert!(!no_permission.unwrap());
}

/// 测试获取用户权限列表
#[tokio::test]
async fn test_get_user_permissions() {
    let config = AuthServiceConfig::default();
    let mock_provider = Arc::new(MockAuthProvider::new("mock", true));
    
    let auth_service = AuthServiceBuilder::new()
        .add_provider("mock".to_string(), mock_provider)
        .with_default_provider("mock".to_string())
        .build()
        .await
        .expect("Failed to build auth service");

    let context = AuthContext::new(
        HashMap::new(),
        "GET".to_string(),
        "/api/test".to_string(),
        Some("127.0.0.1".to_string()),
    );

    let principal = auth_service.authenticate(&context).await.unwrap();
    let permissions = auth_service.get_user_permissions(&principal).await;
    
    assert!(permissions.is_ok());
    let perms = permissions.unwrap();
    assert!(perms.contains(&"read:posts".to_string()));
    assert!(perms.contains(&"write:comments".to_string()));
}

/// 测试配置加载
#[tokio::test]
async fn test_config_loading() {
    // 测试默认配置
    let config = RustCloudAuthConfig::default();
    assert_eq!(config.service.name, "rustcloud-auth");
    assert_eq!(config.service.listen_port, 8080);
    assert!(!config.service.tls_enabled);
    
    // 测试提供者配置
    assert_eq!(config.providers.default_provider, "jwt");
    assert!(!config.providers.providers.is_empty());
}

/// 性能测试 - 并发认证
#[tokio::test]
async fn test_concurrent_authentication() {
    let config = AuthServiceConfig::default();
    let mock_provider = Arc::new(MockAuthProvider::new("mock", true));
    
    let auth_service = Arc::new(
        AuthServiceBuilder::new()
            .add_provider("mock".to_string(), mock_provider)
            .with_default_provider("mock".to_string())
            .build()
            .await
            .expect("Failed to build auth service")
    );

    let mut handles = Vec::new();
    
    // 创建100个并发认证任务
    for i in 0..100 {
        let service = auth_service.clone();
        let handle = tokio::spawn(async move {
            let context = AuthContext::new(
                HashMap::new(),
                "GET".to_string(),
                format!("/api/test/{}", i),
                Some("127.0.0.1".to_string()),
            );
            
            service.authenticate(&context).await
        });
        handles.push(handle);
    }
    
    // 等待所有任务完成
    let results = futures::future::join_all(handles).await;
    
    // 验证所有认证都成功
    for result in results {
        assert!(result.is_ok());
        assert!(result.unwrap().is_ok());
    }
}

/// 测试错误处理
#[tokio::test]
async fn test_error_handling() {
    // 测试没有提供者的情况
    let result = AuthServiceBuilder::new()
        .with_default_provider("nonexistent".to_string())
        .build()
        .await;
    
    assert!(result.is_err());
    
    // 测试默认提供者不存在的情况
    let mock_provider = Arc::new(MockAuthProvider::new("mock", true));
    let result = AuthServiceBuilder::new()
        .add_provider("mock".to_string(), mock_provider)
        .with_default_provider("nonexistent".to_string())
        .build()
        .await;
    
    assert!(result.is_err());
}